/*
 * Copyright (c) 2018, apexes.net. All rights reserved.
 *
 *         http://www.apexes.net
 *
 */
package net.apexes.commons.querydsl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.querydsl.core.types.Path;
import net.apexes.commons.lang.Checks;

/**
 * @author <a href="mailto:hedyn@foxmail.com">HeDYn</a>
 */
public class ExcludeColumns {

    public static ExcludeColumns of(Path<?>... excludeColumns) {
        return new ExcludeColumns(excludeColumns);
    }

    private Path<?>[] excludeColumns;

    public ExcludeColumns(Path<?>... excludeColumns) {
        this.excludeColumns = excludeColumns;
    }

    public ExcludeColumns add(ExcludeColumns exclude) {
        Checks.verifyNotNull(exclude, "exclude");
        if (exclude.excludeColumns != null) {
            return add(exclude.excludeColumns);
        } else {
            return this;
        }
    }

    public ExcludeColumns add(Path<?>... excludeColumns) {
        Checks.verifyNotEmpty(excludeColumns, "excludeColumns");
        List<Path<?>> list = new ArrayList<>(this.excludeColumns.length + excludeColumns.length);
        for (Path<?> column : this.excludeColumns) {
            list.add(column);
        }
        for (Path<?> column : excludeColumns) {
            if (!list.contains(column)) {
                list.add(column);
            }
        }
        this.excludeColumns = list.toArray(new Path<?>[list.size()]);
        return this;
    }

    public ExcludeColumns remove(Path<?>... excludeColumns) {
        if (excludeColumns == null) {
            throw new IllegalArgumentException("(excludeColumns == null)");
        }
        if (excludeColumns.length == 0) {
            throw new IllegalArgumentException("(excludeColumns.length == 0)");
        }
        List<Path<?>> list = new ArrayList<>(this.excludeColumns.length);
        for (Path<?> column : this.excludeColumns) {
            list.add(column);
        }
        for (Path<?> column : excludeColumns) {
            if (list.contains(column)) {
                list.remove(column);
            }
        }
        this.excludeColumns = list.toArray(new Path<?>[list.size()]);
        return this;
    }

    public Path<?>[] getExcludeColumns() {
        if (excludeColumns == null) {
            List<Path<?>> list = new ArrayList<>();
            excludeColumns = list.toArray(new Path<?>[0]);
        }
        return excludeColumns;
    }

    public boolean hasColumns() {
        return (excludeColumns == null || excludeColumns.length == 0) ? false : true;
    }

    public Map<Path<?>, Path<?>> getExcludeColumnsBag() {
        Map<Path<?>, Path<?>> excludeColumnsBag = new HashMap<>();
        for (Path<?> col : excludeColumns) {
            excludeColumnsBag.put(col, col);
        }
        return excludeColumnsBag;
    }

}
